package com.yuanli.card.manage.service;

import org.slf4j.Logger;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.StreamUtils;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;

/**
 * Created by layne on 2019/03/05.
 */
public class LogHttpRequestInterceptor implements ClientHttpRequestInterceptor {

    private final Logger logger;
    private final Charset charset;

    public LogHttpRequestInterceptor(Logger logger, Charset charset) {
        this.logger = logger;
        this.charset = charset;
    }

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        try {
            //记录请求
            StringBuilder logText = new StringBuilder()
                    .append(request.getMethod())
                    .append(' ')
                    .append(request.getURI())
                    .append('\n');
            logHeaders(logText, request.getHeaders());
            logText.append('\n')
                    .append(new String(body, charset));
            logger.info("发起请求：{}", logText);

            ClientHttpResponse response = execution.execute(request, body);

            //记录响应
            logText = new StringBuilder()
                    .append(response.getStatusCode())
                    .append(' ')
                    .append(response.getStatusText())
                    .append('\n');
            logHeaders(logText, response.getHeaders());
            logText.append('\n');
            StringClientHttpResponseWrapper responseWrapper = new StringClientHttpResponseWrapper(response);
            logText.append(responseWrapper.getText());
            logger.info("响应内容：{}", logText);

            return responseWrapper;
        } catch (Exception ex) {
            logger.error("请求发生异常", ex);
            throw ex;
        }
    }

    private void logHeaders(StringBuilder logText, HttpHeaders headers) {
        headers.forEach((name, values) -> {
            for (String value : values) {
                logText.append(name).append(": ").append(value).append('\n');
            }
        });
    }

    private class StringClientHttpResponseWrapper implements ClientHttpResponse {
        private final ClientHttpResponse response;
        private byte[] body;

        public StringClientHttpResponseWrapper(ClientHttpResponse response) {
            this.response = response;
        }

        @Override
        public HttpStatus getStatusCode() throws IOException {
            return response.getStatusCode();
        }

        @Override
        public int getRawStatusCode() throws IOException {
            return response.getRawStatusCode();
        }

        @Override
        public String getStatusText() throws IOException {
            return response.getStatusText();
        }

        @Override
        public void close() {
            response.close();
        }

        @Override
        public InputStream getBody() throws IOException {
            if (this.body == null) {
                this.body = StreamUtils.copyToByteArray(this.response.getBody());
            }
            return new ByteArrayInputStream(this.body);
        }

        @Override
        public HttpHeaders getHeaders() {
            return response.getHeaders();
        }

        public String getText() throws IOException {
            getBody();
            return new String(body, charset);
        }
    }
}
